<script setup>
import {ref, onUnmounted} from "vue"

const game2048 = ref([
  [0, 0, 0, 0],
  [0, 0, 0, 0],
  [0, 0, 0, 0],
  [0, 0, 0, 0]
])

function createNum() {
  if (game2048.value.every(item => item.every(item2 => item2 !== 0))) {
    return
  }
  let x = Math.floor(Math.random() * 4)
  let y = Math.floor(Math.random() * 4)
  if (game2048.value[x][y] === 0) {
    game2048.value[x][y] = Math.random() < 0.5 ? 2 : 4;
  } else {
    createNum()
  }
}

function init() {
  game2048.value = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
  ]
  createNum()
  document.addEventListener("keydown", keyListener)
}

function moveUp() {
  for (let i = 0; i < 4; i++) {
    for (let j = 1; j < 4; j++) {
      for (let k = j; k >= 1; k--) {
        if (game2048.value[k - 1][i] === 0 && game2048.value[k][i] !== 0) {
          game2048.value[k - 1][i] = game2048.value[k][i]
          game2048.value[k][i] = 0
        } else if (game2048.value[k][i] !== 0 && game2048.value[k - 1][i] === game2048.value[k][i]) {
          game2048.value[k - 1][i] += game2048.value[k][i]
          game2048.value[k][i] = 0
        }
      }
    }
  }
}

function moveDown() {
  for (let i = 0; i < 4; i++) {
    for (let j = 3; j > 0; j--) {
      for (let k = 0; k < j; k++) {
        if (game2048.value[k + 1][i] === 0 && game2048.value[k][i] !== 0) {
          game2048.value[k + 1][i] = game2048.value[k][i]
          game2048.value[k][i] = 0
        } else if (game2048.value[k][i] !== 0 && game2048.value[k + 1][i] === game2048.value[k][i]) {
          game2048.value[k + 1][i] += game2048.value[k][i]
          game2048.value[k][i] = 0
        }
      }
    }
  }
}

function moveLeft() {
  for (let i = 0; i < 4; i++) {
    for (let j = 1; j < 4; j++) {
      for (let k = j; k >= 1; k--) {
        if (game2048.value[i][k - 1] === 0 && game2048.value[i][k] !== 0) {
          game2048.value[i][k - 1] = game2048.value[i][k]
          game2048.value[i][k] = 0
        } else if (game2048.value[i][k] !== 0 && game2048.value[i][k - 1] === game2048.value[i][k]) {
          game2048.value[i][k - 1] += game2048.value[i][k]
          game2048.value[i][k] = 0
        }
      }
    }
  }
}

function moveRight() {
  for (let i = 0; i < 4; i++) {
    for (let j = 3; j > 0; j--) {
      for (let k = 0; k < j; k++) {
        if (game2048.value[i][k + 1] === 0 && game2048.value[i][k] !== 0) {
          game2048.value[i][k + 1] = game2048.value[i][k]
          game2048.value[i][k] = 0
        } else if (game2048.value[i][k] !== 0 && game2048.value[i][k + 1] === game2048.value[i][k]) {
          game2048.value[i][k + 1] += game2048.value[i][k]
          game2048.value[i][k] = 0
        }
      }
    }
  }
}

function gameEnd() {
  if (game2048.value.some(item => item.some(item2 => item2 === 2048))) {
    alert("You Win")
    document.removeEventListener("keydown", keyListener)
    return true
  }
  if (game2048.value.every(item => item.every(item2 => item2 !== 0))) {
    for (let i = 0; i < 4; i++) {
      for (let j = 0; j < 4; j++) {
        if ((i < 3 && game2048.value[i][j] === game2048.value[i + 1][j]) || (j < 3 && game2048.value[i][j] === game2048.value[i][j + 1])) {
          return false
        }
      }
    }
    alert("You Lose")
    document.removeEventListener("keydown", keyListener)
    return true
  }
  return false
}

let keyListener = (e) => {
  switch (e.keyCode) {
    case 38:
      // ↑
      moveUp();
      break;
    case 40:
      // ↑
      moveDown();
      break;
    case 37:
      // ←
      moveLeft();
      break;
    case 39:
      // ←
      moveRight();
      break;
  }
  let res = gameEnd()
  if (!res) {
    createNum()
  }
}

onUnmounted(() => {
  document.removeEventListener("keydown", keyListener)
})

init()
</script>

<template>
  <div>
    <div class="mx-auto">
      <div class="mb-5">按键盘方向键操作</div>
      <div class="text-center">
        <el-button @click="init" class="mb-5" type="primary">重新开始</el-button>

        <div v-for="(item, index) in game2048" :key="index" class="flex justify-center">
          <div v-for="(item2, index2) in item" :key="index2"
               class="w-10 h-10 text-center leading-10 border border-black">
            <span>{{ item2 > 0 ? item2 : "" }}</span>
          </div>
        </div>

      </div>
    </div>
  </div>

</template>

<style scoped>

</style>